
    <!DOCTYPE html>
    <html lang="zh-CN">
    <head>
      <meta charset="UTF-8">
      <meta name="viewport" content="width=device-width, initial-scale=1.0">
      <title>并发编程基础 - 学习卡片</title>
      <style>
        body { font-family: sans-serif; background-color: #f0f8ff; color: #333; display: flex; flex-direction: column; align-items: center; padding: 50px 20px; }
        .header h1 { font-size: 32px; }
        .grid-container { display: grid; grid-template-columns: repeat(3, 1fr); gap: 28px; width: 100%; max-width: 1200px; }
        .card-container { perspective: 1200px; cursor: pointer; height: 250px; }
        .card { width: 100%; height: 100%; position: relative; transform-style: preserve-3d; transition: transform 0.7s; border-radius: 16px; box-shadow: 0 4px 16px rgba(0,0,0,0.08); }
        .card-container.flipped .card { transform: rotateY(180deg); }
        .card-face { position: absolute; width: 100%; height: 100%; backface-visibility: hidden; display: flex; flex-direction: column; box-sizing: border-box; border-radius: 16px; background-color: #fff; padding: 24px; }
        .card-back { background-color: #f0fff4; transform: rotateY(180deg); justify-content: space-between; }
        .card-category { font-size: 14px; color: #0052d9; margin-bottom: 8px; font-weight: 500; }
        .card-question { font-size: 20px; font-weight: 500; flex-grow: 1; display: flex; align-items: center; justify-content: center; text-align: center; }
        .card-answer-wrapper { flex-grow: 1; overflow-y: auto; }
        .card-answer { font-size: 15px; line-height: 1.7; }
        .card-footer { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 16px; margin-top: 16px; }
        .card-source { font-size: 13px; color: #8a919f; border-top: 1px solid #f0f0f0; padding-top: 12px; margin-top: 12px; }
      </style>
    </head>
    <body>
      <div class="header">
        <h1>并发编程基础 - 学习卡片</h1>
      </div>
      <div class="grid-container">
        
    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">理论</div>
          <div class="card-question">并发（Concurrency）和并行（Parallelism）的核心区别是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">理论</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">并发指的是在同一时间段内管理多个任务，但不一定是同时执行，可以在单个处理器上通过时间片轮转交替执行。而并行是指在多个处理器核心上真正地同时执行多个任务。因此，并行是并发的一种特殊情况。</div>
          </div>
          <div class="card-source">来源: 并发编程概述 - 1. 并发与并行的区别</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">对比</div>
          <div class="card-question">从资源占用和稳定性的角度看，进程（Process）与线程（Thread）有何根本不同？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">对比</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">资源占用上，每个进程拥有独立的内存空间等资源，而线程共享其所属进程的资源。稳定性上，一个进程的崩溃通常不会影响其他进程，但一个线程的崩溃可能会导致其所在的整个进程崩溃。</div>
          </div>
          <div class="card-source">来源: 进程与线程基础 - 3. 进程与线程的区别</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">技术</div>
          <div class="card-question">在 Java 中创建线程时，为什么说实现 `Runnable` 接口比继承 `Thread` 类的方式更灵活？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">技术</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">因为 Java 不支持类的多重继承。如果一个类已经继承了另一个父类，它就无法再通过继承 `Thread` 类来创建线程。而通过实现 `Runnable` 接口，该类可以自由地继承其他类，从而避免了单继承的限制，因此更加灵活。</div>
          </div>
          <div class="card-source">来源: 线程的创建与启动 - 2. 通过实现 Runnable 接口创建线程</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">调用线程的 `start()` 方法和直接调用 `run()` 方法之间有什么本质区别？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">调用 `start()` 方法是用于启动一个新线程，该新线程会自动执行 `run()` 方法中的任务，这实现了真正的并发。而直接调用 `run()` 方法，则不会创建新线程，它仅仅是在当前线程中执行一个普通的方法调用，整个过程是同步的。</div>
          </div>
          <div class="card-source">来源: 线程的创建与启动 - 4. start() 和 run() 方法的区别</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">对比</div>
          <div class="card-question">同步（Synchronous）与异步（Asynchronous）执行模型在线程阻塞和结果获取方面有何主要差异？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">对比</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">同步操作会阻塞当前线程，程序必须等待任务执行完成并返回结果后才能继续。而异步操作不会阻塞当前线程，任务发起后会立即返回，程序可以继续执行其他操作，任务结果通常通过回调函数或事件监听等机制在未来某个时间点获取。</div>
          </div>
          <div class="card-source">来源: 同步与异步 - 3. 同步与异步的对比</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">工具</div>
          <div class="card-question">信号量（Semaphore）在并发控制中主要扮演什么角色？请举例说明其应用场景。</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">工具</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">信号量是一种用于限制并发访问特定资源数量的工具。它通过维护一个许可计数器来控制同时访问资源的线程数量。例如，它常被用于限制并发的数据库连接数或同时访问某个文件的线程数。</div>
          </div>
          <div class="card-source">来源: 并发控制的基本工具 - 4. 信号量（Semaphore）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">模式</div>
          <div class="card-question">悲观锁和乐观锁在处理并发冲突时的核心思想是什么？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">模式</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">悲观锁的核心思想是假设数据冲突总会发生，因此在每次访问共享资源前都先加锁，确保独占访问。乐观锁则相反，它假设冲突很少发生，操作时不加锁，只在更新数据时通过CAS（比较并交换）或版本号等机制检查数据是否被其他线程修改过。</div>
          </div>
          <div class="card-source">来源: 同步与并发控制 - 3.1 乐观锁与悲观锁</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">工具</div>
          <div class="card-question">阻塞队列（BlockingQueue）是如何在“生产者-消费者”模型中实现线程协作的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">工具</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">阻塞队列通过其内在的阻塞机制来协调生产者和消费者。当队列满时，试图放入元素的生产者线程会被阻塞，直到队列有空间为止。当队列为空时，试图取出元素的消费者线程会被阻塞，直到队列中有元素为止。这样就实现了两者之间的自动同步。</div>
          </div>
          <div class="card-source">来源: 并发控制的基本工具 - 5. 阻塞队列（BlockingQueue）</div>
        </div>
      </div>
    </div>

    <div class="card-container" onclick="this.classList.toggle('flipped');">
      <div class="card">
        <div class="card-face card-front">
          <div class="card-category">机制</div>
          <div class="card-question">`ForkJoinPool` 是如何利用“工作窃取算法”来提高并行计算效率的？</div>
          <div class="card-footer">点击卡片查看答案</div>
        </div>
        <div class="card-face card-back">
          <div class="card-category">机制</div>
          <div class="card-answer-wrapper">
            <div class="card-answer">`ForkJoinPool` 使用“工作窃取算法”来实现负载均衡。具体来说，如果池中的某个线程完成了自己的任务并且处于空闲状态，它会从其他仍然繁忙的线程的任务队列中“窃取”一个任务来执行，从而确保所有处理器核心都得到充分利用。</div>
          </div>
          <div class="card-source">来源: 并发控制的基本工具 - 7. ForkJoinPool</div>
        </div>
      </div>
    </div>

      </div>
    </body>
    </html>
